<?php

namespace app\admin\controller\card;

use app\common\controller\Backend;
use app\common\model\card\entity\Site;
use app\common\model\card\EntitySite;
use app\common\model\card\Kabawlogtype;
use control\RedisClient;
use Exception;
use fast\Random;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use think\Db;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\exception\DbException;
use think\exception\PDOException;
use think\exception\ValidateException;

/**
 * 实体卡
 *
 * @icon fa fa-circle-o
 */
class Entity extends Backend
{

    /**
     * Entity模型对象
     * @var \app\common\model\card\Entity
     */
    protected $model = null;

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new \app\common\model\card\Entity;
        $this->view->assign("statusList", $this->model->getStatusList());
    }


    /**
     * 查看
     */
    public function index()
    {
        //当前是否为关联查询
        $this->relationSearch = true;
        //设置过滤方法
        $this->request->filter(['strip_tags', 'trim']);
        if ($this->request->isAjax()) {
            //如果发送的来源是Selectpage，则转发到Selectpage
            if ($this->request->request('keyField')) {
                return $this->selectpage();
            }
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();

            $list = $this->model
                ->where($where)
                ->order($sort, $order)
                ->paginate($limit);

            foreach ($list as $row) {
                $logtype = Kabawlogtype::field("card_type_name,number,price")
                    ->where(["card_kabaw_id" => $row["card_kabaw_id"], "card_kabaw_entity_id" => $row["id"]])->select();
                $logtype_str = "";
                if (!empty($logtype)) {
                    foreach ($logtype as $k => $vs) {
                        if (empty($k)) {
                            $logtype_str = "<p>" . $vs["card_type_name"] . "(" . $vs["number"] . "次)</p>";
                        } else {
                            $logtype_str .= "<p>" . $vs["card_type_name"] . "(" . $vs["number"] . "次)</p>";
                        }
                    }
                }
                $row["logtype"] = $logtype_str;
            }
            $result = array("total" => $list->total(), "rows" => $list->items());

            return json($result);
        }
        return $this->view->fetch();
    }

    protected function check($params, $edit_status = 0)
    {
        $data = [
            ['card_kabaw_id', 'require', '请选择卡包'],
            ['number', 'require|^[1-9]\d*$', '请填写数量|请填写大于0的数'],
        ];
        $validate = new \think\Validate($data);
        if (!$validate->check($params)) {
            $this->error('提交失败：' . $validate->getError());
        }
        $kabaw = [];
        if ((isset($params["id"]) && $edit_status == 1) || !isset($params["id"])) {
            $kabaw = \app\common\model\card\Kabaw::get($params["card_kabaw_id"]);
            if (empty($kabaw)) $this->error('提交失败：卡包不存在');
            //if ($kabaw["online_switch"] != 1) $this->error('提交失败：卡包未上线');
        }
        if ($params["number"] > 10000) $this->error('最多只能印刷10000张');
        return ["code" => true, "kabaw" => $kabaw];
    }

    /**
     * 添加
     *
     * @return string
     * @throws \think\Exception
     */
    public function add()
    {

        if (false === $this->request->isPost()) {
            return $this->view->fetch();
        }
        $params = $this->request->post('row/a');
        if (empty($params)) {
            $this->error(__('Parameter %s can not be empty', ''));
        }
        $params = $this->preExcludeFields($params);

        if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
            $params[$this->dataLimitField] = $this->auth->id;
        }
        $result = false;
        $res = $this->check($params);
        if (!$res["code"]) return $res;
        $RedisClient=new RedisClient();
        $lockVal=md5(time().rand("000000","999999"));
        $redisLock=$RedisClient->setNx('card_creat_lock',$lockVal,300);
        if(!$redisLock) $this->error("有卡片正在生成！请稍后在试!");
        Db::startTrans();
        try {
            //是否采用模型验证
            if ($this->modelValidate) {
                $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
                $this->model->validateFailException()->validate($validate);
            }
            $params["kabaw_name"] = $res["kabaw"]["name"];
            $params["kabaw_illustrate"] = $res["kabaw"]["illustrate"];
            $params["kabaw_fate"] = $res["kabaw"]["fate"];
            $params["kabaw_all_cost"] = $res["kabaw"]["all_cost"];
            $params["kabaw_all_price"] = $res["kabaw"]["all_price"];
            $params["createtime"] = time();
            $result = $this->model->allowField(true)->insertGetId($params);
            /*新增生成实体卡-卡包相关配置 start*/
            $site = [
                "kabaw_name" => $res["kabaw"]["name"],
                "card_entity_id" => $result,
                "card_kabaw_id" => $params["card_kabaw_id"],
                "kabaw_illustrate" => $res["kabaw"]["illustrate"],
                "kabaw_fate" => $res["kabaw"]["fate"],
                "kabaw_all_cost" => $res["kabaw"]["all_cost"],
                "kabaw_all_price" => $res["kabaw"]["all_price"],
            ];
            if (!empty($site)) {
                EntitySite::create($site);
            }
            /*新增生成实体卡-卡包相关配置 end*/
            Db::commit();
            $RedisClient->delNx('card_creat_lock',$lockVal);
        } catch (ValidateException|PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        if ($result === false) {
            $this->error(__('No rows were inserted'));
        }
        $this->success();
    }

    /**
     * 编辑
     *
     * @param $ids
     * @return string
     * @throws DbException
     * @throws \think\Exception
     */
    public function edit($ids = null)
    {
        $row = $this->model->get($ids);
        if (!$row) {
            $this->error(__('No Results were found'));
        }
        $adminIds = $this->getDataLimitAdminIds();
        if (is_array($adminIds) && !in_array($row[$this->dataLimitField], $adminIds)) {
            $this->error(__('You have no permission'));
        }
        if (false === $this->request->isPost()) {
            $this->view->assign('row', $row);
            return $this->view->fetch();
        }
        $params = $this->request->post('row/a');
        if (empty($params)) {
            $this->error(__('Parameter %s can not be empty', ''));
        }
        $params = $this->preExcludeFields($params);
        $result = false;
        $edit_status = $row["card_kabaw_id"] != $params["card_kabaw_id"] ? 1 : 0;
        $res = $this->check($params, $edit_status);
        if (!$res["code"]) return $res;
        Db::startTrans();
        try {
            //是否采用模型验证
            if ($this->modelValidate) {
                $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
                $row->validateFailException()->validate($validate);
            }
            $params["kabaw_name"] = $res["kabaw"]["name"];
            $params["kabaw_illustrate"] = $res["kabaw"]["kabaw_illustrate"];
            $params["kabaw_fate"] = $res["kabaw"]["kabaw_fate"];
            $params["kabaw_all_cost"] = $res["kabaw"]["kabaw_all_cost"];
            $params["kabaw_all_price"] = $res["kabaw"]["kabaw_all_price"];
            $result = $this->model->allowField(true)->insertGetId($params);
            $result = $row->allowField(true)->save($params);
            /*if ($edit_status == 1) {
                //修改卡包后
                $site_table = EntitySite::get(["card_entity_id" => $ids]);
                $log = \app\common\model\card\Entitylog::where(["card_entity_id" => $site_table["id"]])->find(1);
                $site = [
                    "kabaw_name" => $res["kabaw"]["name"],
                    "card_entity_id" => $ids,
                    "card_kabaw_id" => $params["card_kabaw_id"],
                    "kabaw_illustrate" => $res["kabaw"]["illustrate"],
                    "kabaw_fate" => $res["kabaw"]["fate"],
                    "kabaw_all_cost" => $res["kabaw"]["all_cost"],
                    "kabaw_all_price" => $res["kabaw"]["all_price"],
                ];
                if (!empty($site)) {
                    if (!empty($log)) {
                        $model = new EntitySite();
                        $site["id"] = $site_table["id"];
                        $model->saveAll($site);
                    } else {
                        EntitySite::create($site);
                    }
                }
            }*/
            Db::commit();
        } catch (ValidateException|PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        if (false === $result) {
            $this->error(__('No rows were updated'));
        }
        $this->success();
    }

    /**
     * 删除
     *
     * @param $ids
     * @return void
     * @throws DbException
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     */
    public function del($ids = null)
    {
        if (false === $this->request->isPost()) {
            $this->error(__("Invalid parameters"));
        }
        $ids = $ids ?: $this->request->post("ids");
        if (empty($ids)) {
            $this->error(__('Parameter %s can not be empty', 'ids'));
        }
        $pk = $this->model->getPk();
        $adminIds = $this->getDataLimitAdminIds();
        if (is_array($adminIds)) {
            $this->model->where($this->dataLimitField, 'in', $adminIds);
        }
        $list = $this->model->where($pk, 'in', $ids)->select();

        $count = 0;
        Db::startTrans();
        try {
            foreach ($list as $item) {
                $count += $item->delete();
            }

            Db::commit();
        } catch (PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        if ($count) {
            $this->success();
        }
        $this->error(__('No rows were deleted'));
    }

    /**
     * 印刷
     * */
    public function printAll()
    {
        if (!$this->request->param("ids")) $this->error('id为空');
        $param = $this->request->param();
        $row = $this->model->get($param["ids"]);
        if (!$row) {
            $this->error(__('No Results were found'));
        }
        $kabaw = \app\common\model\card\Kabaw::get($row["card_kabaw_id"]);
        if (empty($kabaw)) $this->error("卡包不存在");
        //if ($kabaw["online_switch"] != 1) $this->error("请先将卡包上线");
        $update_data = [
            "updatetime" => time(),
            "status" => '1',
        ];
        $result = false;
        Db::startTrans();
        $RedisClient=new RedisClient();
        $lockVal=md5(time().rand("000000","999999"));
        $redisLock=$RedisClient->setNx('card_dump_lock',$lockVal,300);
        if(!$redisLock) $this->error("有卡片正在印刷！请稍后在试!");
        try {
            $site = EntitySite::where(["card_entity_id" => $row["id"]])->find();
            if (empty($row["status"])) {
                $exchange_number=$this->getexchangeNumber();
                /******** 生成实体卡记录 start****************/
                for ($i = 1; $i <= $row["number"]; $i++) {
                    $data[$i] = [
                        "card_entity_site_id" => $site["id"],
                        "card_entity_id" => $row["id"],
                        "code" =>$this->getcode(6) ,//兑换密码
                        "exchange_number" => $exchange_number,//兑换号码
                        "createtime" => time(),//兑换号码
                    ];
                    if($i>1) {
                        $exchange_number=$this->getexchangeNumber($exchange_number);
                        $data[$i]["exchange_number"] = $exchange_number;
                    }
                }
                \app\common\model\card\Entitylog::insertAll($data);//生成实体卡
                /******** 生成实体卡记录 end****************/
                $number_from = \app\common\model\card\Entitylog::field("id")->where(["card_entity_id" => $row["id"]])->order("id", "asc")->find();
                $number_to= \app\common\model\card\Entitylog::field("id")->where(["card_entity_id" => $row["id"]])->order("id", "desc")->find();
                $update_data["number_from"] = $number_from["id"];
                $update_data["number_to"] = $number_to["id"];
                /******** 导出 start****************/

                /******** 生成实体卡记录 start****************/
                $type = \app\common\model\card\Kabawtype::where(["card_kabaw_id" => $kabaw["id"]])->select();
                if (!empty($type)) {
                    foreach ($type as $k => $v) {
                        $logtype[$k] = [
                            "card_type_name" => $v["card_type_name"],
                            "card_type_id" => $v["card_type_id"],
                            "card_kabaw_id" => $kabaw["id"],
                            "number" => $v["number"],
                            "price" => $v["price"],
                            "all_cost" => $v["all_cost"],
                            "card_kabaw_entity_id" => $row["id"],
                            "highest_price" => $v["highest_price"],
                        ];
                    }
                    Kabawlogtype::insertAll($logtype);
                }
                /******** 生成实体卡记录 end****************/
            }

            /******** 导出 start****************/
            $log = \app\common\model\card\Entitylog::with(['site' => function ($query) {
                $query->withField('kabaw_name,kabaw_fate,card_kabaw_id');
            }])
                ->where(["card_entity_site_id" => $site["id"]])->select();
            foreach ($log as &$v) {
                $logtype = Kabawlogtype::field("card_type_name,number,price")
                    ->where(["card_kabaw_id" => $v["site"]["card_kabaw_id"], "card_kabaw_entity_id" => $row["id"]])->select();
                $logtype_str = "";
                if (!empty($logtype)) {
                    foreach ($logtype as $k => $vs) {
                        if (empty($k)) {
                            $logtype_str = $vs["card_type_name"] . "(" . $vs["number"] . "次)";
                        } else {
                            $logtype_str .= "\n" . $vs["card_type_name"] . "(" . $vs["number"] . "次)";
                        }
                    }
                }
                $v["logtype"] = $logtype_str;
            }
            $res = $this->export_data($log, $row["id"]);
            $update_data["updatetime"] = time();
            $result = $row->allowField(true)->save($update_data);
            /******** 导出 end****************/
            $result = true;
            Db::commit();
            $RedisClient->delNx('card_creat_lock',$lockVal);
        } catch (ValidateException|PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        if ($result !== false) {
            $this->success("印刷成功", $res);
        } else {
            $this->error(__('No rows were updated'));
        }
    }

    /**
     * 生成6位数字
     * */
    protected function getcode($num = 6, $type = 0)
    {
        $code = Random::numeric($num);
        if ($type == 1) {
            $log = \app\common\model\card\Entitylog::field("1")->where(["exchange_number" => $code])->find();
            if (!empty($log)) {
                $this->getcode($num);
            }
        } else {
            $log = \app\common\model\card\Entitylog::field("1")->where(["code" => $code])->find();
            if (!empty($log)) {
                $this->getcode($num);
            }
        }
        return $code;
    }

    /**
     * 生成兑换号码
     * */
    protected function getexchangeNumber($code="")
    {
        if(empty($code)){
            $code = "000000001";
        }else{
            $code=(int)$code+1;
            $code=sprintf("%09d",$code);
        }
        $code_log = \app\common\model\card\Entitylog::where(["exchange_number" => $code])->find();
        if (!empty($code_log)) {
            //1334
            $code_max = \app\common\model\card\Entitylog::where(" id > 1334")
                ->orderRaw("CAST(exchange_number as UNSIGNED) desc")
                ->find();
            $code=(int)$code_max["exchange_number"]+1;
            $code=sprintf("%09d",$code);
        }
        $log = \app\common\model\card\Entitylog::field("exchange_number")->where(["exchange_number" => $code])->find();
        if (!empty($log)) {
            $this->getexchangeNumber($log["exchange_number"]);
        }
        return $code;
    }

    /**
     * @author TechKoga
     * @date 2022/2/16
     * @describe 导出
     */
    public function export_data($dataArr, $id = 0)
    {
        if ($this->request->isAjax()) {
            $header = ['编号', '卡券类型', '卡包名称', '印刷编号', '兑换号码', '兑换密码', '使用有效期（天）'];
            set_time_limit(0);
            $f_name = '实体卡_';
            $file_Name = $f_name . $id;

            //文件存放文件夹不存在则创建
            if (!file_exists('./uploads/csv/')) {
                @mkdir("./uploads/csv/", 0777, true);
            }
            //文件路径
            $filepath = "/uploads/csv/" . $file_Name . '.csv';
            $file = fopen('.' . $filepath, "w"); //打开csv文件，如果不存在则创建
            fwrite($file, chr(0xEF) . chr(0xBB) . chr(0xBF));
            //写入头部栏目
            fputcsv($file, $header);
            foreach ($dataArr as $kk => $a) {
                //数据格式转换成 utf8
                /*$a->merchant = iconv('gb2312','utf-8',$a->merchant);
                $a->createtime = date('Y-m-d H:i:s', $a->createtime);*/
                //写入csv
                $data = [
                    "id" => $a["id"],
                    "logtype" => $a["logtype"],
                    "kabaw_name" => $a["site"]["kabaw_name"],
                    "card_entity_id" => $id,
                    "exchange_number" => $a["exchange_number"] . "\t",
                    "code" => $a["code"] . "\t",
                    "kabaw_fate" => $a["site"]["kabaw_fate"],
                ];
                fputcsv($file, $data);
            }
            //获取当前域名
            $domain = request()->domain();
            //输出下载地址
            return $domain . $filepath;
            $this->success('导出成功', $domain . $filepath);
        }
    }

    /**
     * 导出
     * */
    public function export($list, $total = 0)
    {
        if ($this->request->isPost()) {
            if ($total <= 0) return false;
            //当前是否为关联查询
            set_time_limit(0);
            $spreadsheet = new Spreadsheet();
            $spreadsheet->getProperties()
                ->setCreator("FastAdmin")
                ->setLastModifiedBy("FastAdmin")
                ->setTitle("标题")
                ->setSubject("Subject");
            $spreadsheet->getDefaultStyle()->getFont()->setName('Microsoft Yahei');
            $spreadsheet->getDefaultStyle()->getFont()->setSize(12);

            $worksheet = $spreadsheet->setActiveSheetIndex(0);
            $title = ['ID', '卡包名称', '印刷卡号', '兑换码', '使用有效期（天）'];
            $columns = 'id,name,id,code,kabaw_fate';
            $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
            $sheet = $spreadsheet->getActiveSheet();
            // 方法一，使用 setCellValueByColumnAndRow
            //表头
            //设置单元格内容
            foreach ($title as $key => $value) {
                // 单元格内容写入
                $sheet->setCellValueByColumnAndRow($key + 1, 1, $value);
            }
            $newdata = [];
            foreach ($list as $k => $v) {
                $newdata[$k] = [
                    "id" => $v["id"],
                    "name" => $v["name"] ?? '',
                    "id" => $v["id"] ?? '',
                    "code" => $v["code"] ?? '',
                    "kabaw_fate" => $v["kabaw_fate"] ?? '',
                ];
            }
            $row = 2; // 从第二行开始
            foreach ($newdata as $item) {
                $column = 1;
                foreach ($item as $k => $value) {
                    $sheet->setCellValueByColumnAndRow($column, $row, $value);
                    $column++;
                }
                $row++;
            }

            $fileName = date('Y-m-d') . '_test';
            header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
            header('Content-Disposition: attachment;filename=' . $fileName . '.xlsx');
            header('Cache-Control: max-age=0');
            // If you're serving to IE 9, then the following may be needed
            header('Cache-Control: max-age=1');

            // If you're serving to IE over SSL, then the following may be needed
            header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified
            header('Cache-Control: cache, must-revalidate'); // HTTP/1.1
            header('Pragma: public'); // HTTP/1.0

            $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx');
            $writer->save($fileName . '.xlsx');
            header('location:http://txtest.westts.cn/' . $fileName . ".xlsx");
            die();
            $writer->save('php://output');
            die();

            $first = array_keys($list[0]);
            foreach ($first as $index => $item) {
                $worksheet->setCellValueByColumnAndRow($index, 1, __($item));
            }
            $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load(ROOT_PATH . 'public/assets/muban.xlsx');  //读取模板
            $worksheet = $spreadsheet->getActiveSheet();     //指向激活的工作表
            $worksheet->setTitle('模板测试标题');
            for ($i = 0; $i < $total; ++$i) {
                //向模板表中写入数据
                $i++;
                $columns = 'workID,hospital.name,equipment.name,equipment.marking,equipment.serial,sale.nickname,engineer.nickname,final_price';
                $worksheet->getCell('A' . $i)->setValue($result['rows'][$i]['id']);    //星期
                $worksheet->getCell('B' . $i)->setValue($result['rows'][$i]["name"]);    //星期
                $worksheet->getCell('C' . $i)->setValue($result['rows'][$i]["id"]);  //性别
                $worksheet->getCell('D' . $i)->setValue($result['rows'][$i]['code']);  //爱好
                $worksheet->getCell('E' . $i)->setValue($result['rows'][$i]['kabaw_fate']);  //标题
                $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xls');
                //下载文档
                header('Content-Type: application/vnd.ms-excel');
                header('Content-Disposition: attachment;filename="' . date('Y-m-d') . '_test' . '.xlsx"');
                header('Cache-Control: max-age=0');
                $writer->save('php://output');

            }
            return;
        }
    }
}
